﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using PM.Entity;
using PM.Services;
using System.Collections;
using System.Data.OracleClient;


namespace PM.Common
{
    public class FileLoadServices
    {

        String TradeHdrFile = "Headers\\Trade.hdr";
        String OrderHdrFile = "Headers\\Order.hdr";
        String TrsumHdrFile = "Headers\\trsum.hdr";
        String CDSRegiHdrFile = "Headers\\CDS_Tran.hdr";

        public int AllLines { get; set; }
        public int TradeLines { get; set; }
        public int OrderLines { get; set; }
        public int TrsumLines { get; set; }
        public int CDSLines { get; set; }
        

        int LineWidth = 0;
        static Dictionary<String, int> mapOffset = new Dictionary<String, int>();
        static Dictionary<String, int> mapSize = new Dictionary<String, int>();
        static ArrayList errorList = new ArrayList();

        public void LoadFile(string inputFilePath)
        {

            try
            {
               // using (StreamReader sr = new StreamReader(inputFilePath))
                //{
                //    String line;



                    ReadDataFile(inputFilePath);
                    // Read and display lines from the file until the end of
                    // the file is reached.
                    //while ((line = sr.ReadLine()) != null)
                    //{
                    //    Console.WriteLine(line);

                    //}
                //}
            }
            catch (Exception e)
            {
                throw e;
            }

        }


        private void ReadHdrFile(String FilePath, int StartRow)
        {
            try
            {
                mapOffset.Clear();
                mapSize.Clear();
                string[] lines = System.IO.File.ReadAllLines(FilePath);
                int count = 0;
                int offset = 0;
                //System.Console.WriteLine("No of Lines :" + lines.Length);
                foreach (string line in lines)
                {
                    count++;
                    if (count < StartRow)
                        continue;

                    String header = line.Substring(0, 20).Trim();
                    String size = line.Substring(32, 2);
                    int iSize = 0;
                    try
                    {
                        iSize = Int16.Parse(size);
                    }
                    catch (Exception ee)
                    {
                        continue;
                    }
                    mapSize.Add(header, iSize);
                    mapOffset.Add(header, offset);

                    //Console.WriteLine(ClmName + " " + iSize + " " + Offset);
                    offset = iSize + offset;
                }
                LineWidth = offset;

                //System.Console.WriteLine("No of ele :" + mapOffset.Count() + "   " + count);
            }
            catch (Exception fileEx)
            {
                throw fileEx;
            }
        }

        static String GetValue(String Header, String Line)
        {
            String value = "";
            value = Line.Substring(mapOffset[Header], mapSize[Header]);
            return value.Trim();
        }

        private void ReadDataFile(String FilePath)
        {
           
            //Db Connection
            OracleConnection con = new OracleConnection();
            con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            con.Open();
            OracleTransaction tran = con.BeginTransaction();  
            try
            {

                string[] lines = File.ReadAllLines(FilePath);

                int transId = 0;
                int count = 0;
                int Offset = 0;

                bool bolTrades = false;
                bool bolOrders = false;
                bool bolTrsum = false;
                bool bolCDSTran = false;

                TradeLines = OrderLines = TrsumLines = CDSLines = 0;              
            

                foreach (string line in lines)
                {
                    AllLines++;
                    if (line.Equals("#Trades"))
                    {
                        mapOffset.Clear();
                        mapSize.Clear();
                        ReadHdrFile(TradeHdrFile, 6);
                        bolTrades = true;
                        bolOrders = false;
                        bolTrsum = false;
                        bolCDSTran = false;
                        continue;
                    }
                    else if (line.Equals("#Orders"))
                    {
                        mapOffset.Clear();
                        mapSize.Clear();
                        ReadHdrFile(OrderHdrFile, 4);
                        bolOrders = true;
                        bolTrades = false;
                        bolTrsum = false;
                        bolCDSTran = false;
                        continue;
                    }
                    else if (line.Equals("#Trsum"))
                    {
                        mapOffset.Clear();
                        mapSize.Clear();
                        ReadHdrFile(TrsumHdrFile, 3);
                        bolTrsum = true;
                        bolTrades = false;
                        bolOrders = false;
                        bolCDSTran = false;
                        continue;
                    }
                    else if (line.Equals("#CDSTran"))
                    {
                        mapOffset.Clear();
                        mapSize.Clear();
                        bolCDSTran = true;
                        bolTrades = false;
                        bolOrders = false;
                        bolTrsum = false;
                        ReadHdrFile(CDSRegiHdrFile, 3);
                        continue;
                    }
                    else
                    {
                        
                        if (bolTrades)
                        {
                            ReadTradeLine(line, con, tran);
                            TradeLines++;
                        }
                        else if (bolOrders)
                        {
                            ReadOrderLine(line, con, tran);
                            OrderLines++;
                        }
                        else if (bolTrsum)
                        {
                            if (transId == 0)
                            {
                                transId = TransactionServices.GetNextTransId(con, tran);
                            }
                            ReadTrsumLine(line, transId, con, tran);
                            transId++;
                            TrsumLines++;
                        }
                        else if (bolCDSTran)
                        {
                            ReadCdstranLine(line, con, tran);
                            CDSLines++;
                        }
                    }
                }
                //COMMIT
                tran.Commit();

            }
            catch (Exception ex)
            {
                //ROOLBACK
                tran.Rollback();
                throw ex;
            }

        }

        private void ReadTradeLine(string line, OracleConnection con, OracleTransaction tran)
        {
            if (line.Length == LineWidth)
            {
                Trade trade = new Trade();

                trade.TradeDate = GetValue("trade_date", line);
                trade.TradeTime = GetValue("trade_time", line);
                trade.BuySell = GetValue("buy_sell", line);
                trade.ExecutionId = GetValue("execution_id", line);
                trade.CompanyId = GetValue("company_id", line);
                trade.MainType = GetValue("main_type", line);
                trade.SubType = GetValue("sub_type", line);
                trade.Quantity = Int32.Parse(GetValue("quantity", line));
                trade.Price = Double.Parse(GetValue("price", line));
                trade.LotType = GetValue("lot_type", line);
                trade.TaxFlag = Int32.Parse(GetValue("tax_flag", line));
                trade.BrokerIdBuy = GetValue("broker_id_buy", line);
                trade.BrokerIdSell = GetValue("broker_id_sell", line);
                trade.BuyingContractNo = Int32.Parse(GetValue("buying_contract_no", line));
                trade.SellingContractNo = Int32.Parse(GetValue("selling_contract_no", line));
                trade.ClientPrefix = Int32.Parse(GetValue("client_prefix", line));
                trade.ClientSuffix = GetValue("client_suffix", line);
                trade.JointAcNo = Int32.Parse(GetValue("joint_ac_no", line));
                trade.ParticipantId = GetValue("participant id", line);
                trade.ForeignFlag = Int32.Parse(GetValue("foreign_flag", line));
                trade.Brokerage = Double.Parse(GetValue("brokerage", line));
                trade.CdsFees = Double.Parse(GetValue("cds_fees", line));
                trade.CseFees = Double.Parse(GetValue("cse_fees", line));
                trade.StampDuty = Double.Parse(GetValue("stamp_duty", line));
                trade.SecCess = Double.Parse(GetValue("sec_cess", line));
                trade.Btt = Double.Parse(GetValue("btt", line));
                trade.InterestOnDebt = Double.Parse(GetValue("interest_on_debt", line));
                trade.OrderId = GetValue("order_id", line);
                trade.TranId = GetValue("tran_id", line);
                trade.Status = Int32.Parse(GetValue("status", line));
                trade.GovernmentCess = Double.Parse(GetValue("government cess", line));

                TradeServices.Add(trade,con,tran);
                

                //UpdatePortfolio
                String clientId = trade.ParticipantId + "-" +
                                    trade.ClientPrefix + "-" +
                                    trade.ClientSuffix + "-" +
                                    trade.JointAcNo;
                String securityId = trade.CompanyId + "-" + trade.MainType + "-" + trade.SubType;
                UpdatePortfolio(clientId, securityId, trade.Quantity, trade.Price, con, tran); 
            }
            else
            {
                errorList.Add(AllLines.ToString());       
            }

        }

        private void ReadOrderLine(string line, OracleConnection con, OracleTransaction tran)
        {
            if (line.Length == LineWidth)
            {
                Order order = new Order();

                order.OrderId = OrderServices.GetNextOrderId(con,tran);

                order.ClienId = GetValue("client_id", line);
                order.SecurityId = GetValue("security_id", line);
                order.OriginalQty = Int32.Parse(GetValue("original_qty", line));
                order.Price = Double.Parse(GetValue("price", line));
                order.OrderDateTime = GetValue("order_date_time", line);
                order.OrderType = GetValue("order_type", line);
                order.BrokerRef = GetValue("broker_ref", line);
                order.Tif = GetValue("tif", line);
                order.TifDays = Int32.Parse(GetValue("tif_days", line));
                order.LotType = GetValue("lot_type", line);
                order.OriginalOrderId = GetValue("order_id", line);
                order.TranId = GetValue("tran_id", line);
                order.BuySell = GetValue("buy_sell", line);
                order.MinFillQty = Int32.Parse(GetValue("min_fill_qty", line));
                order.ForeignBroker = Int32.Parse(GetValue("foreign_broker", line));
                order.TradeId = GetValue("trader_id", line);
                order.BrokerOffice = GetValue("broker_office", line);

                OrderServices.Add(order, con, tran);


            }
            else
            {
                errorList.Add(AllLines.ToString());
            }
        }

        private void ReadTrsumLine(string line, int transId, OracleConnection con, OracleTransaction tran)
        {
            if (line.Length == LineWidth)
            {               
                
                Transaction trsum = new Transaction();
                trsum.TransactionId = transId;
                trsum.TradeDate = GetValue("trade_date", line);
                trsum.SecurityId = GetValue("security_id", line);
                trsum.Description = GetValue("description", line);
                trsum.BidPrice = Double.Parse(GetValue("bid_price", line));
                trsum.AskPrice = Double.Parse(GetValue("ask_price", line));
                trsum.OpenPrice = Double.Parse(GetValue("open_price", line));
                trsum.HighPrice = Double.Parse(GetValue("high_price", line));
                trsum.LowPrice = Double.Parse(GetValue("low_price", line));
                trsum.LastTradedPrice = Double.Parse(GetValue("last_traded_price", line));
                trsum.ClosePrice = Double.Parse(GetValue("close_price", line));
                trsum.TradeVolume = Int64.Parse(GetValue("trade_volume", line));
                trsum.ShareVolume = Int64.Parse(GetValue("share_volume", line));
                trsum.TurnOver = Double.Parse(GetValue("turnover", line));
                trsum.IssuedQuantity = Int64.Parse(GetValue("issued_quantity", line));

                //Check security
                String securityId = GetValue("security_id", line);
                Security security = SecurityServices.GetSecurityById(securityId, con, tran);
                if (security == null)
                {
                    security = new Security(securityId);
                    security.MarketValue = trsum.ClosePrice;
                    security.LastModDate = DateTime.Today;
                    security.Name = trsum.Description;

                    SecurityServices.Add(security,con, tran);
                }
                else
                {
                    security.MarketValue = trsum.ClosePrice;
                    security.LastModDate = DateTime.Today;

                    if (security.Name == security.SecurityId)
                    {
                        security.Name = trsum.Description;
                    }
                    SecurityServices.Update(security,con, tran);
                }

                TransactionServices.Add(trsum,con, tran);
            }
            else
            {
                errorList.Add(AllLines.ToString());
            }
            
            
        }

        private void ReadCdstranLine(string line, OracleConnection con, OracleTransaction tran)
        {
            if (line.Length == LineWidth)
            {
                CDSTransaction cdsTrans = new CDSTransaction();

                cdsTrans.CDSTranId = CDSTransactionServices.GetNextCDSTransactionId(con, tran);

                cdsTrans.TransactionDate = GetValue("transaction_date", line);
                cdsTrans.Reference = GetValue("reference", line);
                cdsTrans.CompanyId = GetValue("company_id", line);
                cdsTrans.MainType = GetValue("main_type", line);
                cdsTrans.SubType = Int32.Parse(GetValue("sub_type", line));
                cdsTrans.ClientPrefix = Int32.Parse(GetValue("client_prefix", line));
                cdsTrans.ClientSuffix = GetValue("client_suffix", line);
                cdsTrans.JointAcNo = Int32.Parse(GetValue("joint_ac_no", line));
                cdsTrans.TransactionType = Int32.Parse(GetValue("transaction_type", line));
                cdsTrans.TransactionDesc= GetValue("transaction_desc", line);
                cdsTrans.Quantity= Int32.Parse(GetValue("quantity", line));
                
                int intTemp = 0;
                if (Int32.TryParse(GetValue("trade_date", line),out intTemp))
                {                  
                    cdsTrans.TradeDate = intTemp;
                } 
                CDSTransactionServices.Add(cdsTrans, con, tran);

                //UpdatePortfolio
                String clientId = "DSA-" +
                                    cdsTrans.ClientPrefix.ToString() + "-" +
                                    cdsTrans.ClientSuffix + "-" +
                                    "0" + cdsTrans.JointAcNo;

                String securityId = cdsTrans.CompanyId + "-" + cdsTrans.MainType + "-" + cdsTrans.SubType;
                UpdatePortfolio(clientId, securityId, cdsTrans.Quantity, 0, con, tran); 
            
            }
            else
            {
                errorList.Add(AllLines.ToString());
            }

        }


        private void UpdatePortfolio(String clientId, String securityId, long quantity, double price, OracleConnection con, OracleTransaction tran)
        {

            Client client = ClientServices.GetClientByCDSId(clientId);

            if (client == null)
            {
                //Invalid client
                return;
            }

            Security security = SecurityServices.GetSecurityById(securityId, con, tran );
            if (security == null)
            {
                security = new Security();
                security.SecurityId = securityId;
                security.Name = securityId;

                SecurityServices.Add(security, con, tran);
            }


            Portfolio clientPort = PortfolioServices.GetPortfolioById(clientId, securityId, con, tran);

            if (clientPort == null)
            {
                clientPort = new Portfolio();
                clientPort.ClientId = clientId;
                clientPort.SecurityId = securityId;
                clientPort.Quantity = quantity;
                clientPort.AvgValue = price;
                PortfolioServices.Add(clientPort, con, tran);

            }
            else
            {
                long prevQuantity = clientPort.Quantity;
                clientPort.Quantity += quantity;
                if (clientPort.Quantity == 0)
                {
                    PortfolioServices.Delete(clientId, securityId, con, tran);
                }
                else
                {
                    double prevAvg = clientPort.AvgValue;
                    clientPort.AvgValue = ((price * quantity) + (prevAvg * prevQuantity)) / clientPort.Quantity;

                    PortfolioServices.Update(clientPort,con, tran);                    
                }

            }

        }


     

    }
}

